package com.ys.erp.stage_user_service.service;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsStringUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.*;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_user_service.bean.condition.UserCondition;
import com.ys.erp.stage_user_service.bean.vo.MemberLevelVO;
import com.ys.erp.stage_user_service.bean.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author lwj
 * @date 2025/5/29
 */
@RequiredArgsConstructor
@Service
@RefreshScope
@Log4j
public class UserService {

    private final IUserService iUserService;

    private final IUserCatService iUserCatService;

    private final IOrderService iOrderService;

    private final IMemberLevelService iMemberLevelService;

    private final IUserPulseService iUserPulseService;

    /**
     * 分页用户
     *
     * @param empDto                登录员工
     * @param con                   请求体
     * @return                      分页数据
     */
    public PageDTO<UserVO> pageUser(StageEmpDTO empDto, UserCondition.PageUserCon con) {
        //构造条件
        QueryWrapper<User> userQw = new QueryWrapper<>();
        if (ObjectUtils.isNotEmpty(con.getPhone())) {
            userQw.lambda().eq(User::getPhone, con.getPhone());
        }
        if (ObjectUtils.isNotEmpty(con.getMemberLevelId())) {
            userQw.lambda().eq(User::getVipLevelId, con.getMemberLevelId());
        }
        if (ObjectUtils.isNotEmpty(con.getName())) {
            userQw.lambda().and(wrapper -> wrapper.like(User::getNickName, con.getName())
                    .or()
                    .like(User::getRealName, con.getName()));
        }
        if (ObjectUtils.isNotEmpty(con.getCatCode())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().eq(UserCat::getCatCode, con.getCatCode());
            List<Long> collect = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).collect(Collectors.toList());
            collect.add(0L);
            userQw.lambda().in(User::getId, collect);
        }
        if (ObjectUtils.isNotEmpty(con.getShopName())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().like(UserCat::getShopName, con.getShopName().substring(0, con.getShopName().indexOf("(")));
            List<Long> collect = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                userQw.lambda().in(User::getId, collect);
            }
        }
        if (ObjectUtils.isNotEmpty(con.getMaintainPhone())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().like(UserCat::getMaintainPhone, con.getMaintainPhone())
                    .isNotNull(UserCat::getMaintainPhone);
            if (PageUserCatQw(userQw, userCatQw)) return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        if (ObjectUtils.isNotEmpty(con.getId())) {
            userQw.lambda().eq(User::getId, con.getId());
        }
        if (ObjectUtils.isNotEmpty(con.getIsCanWriteOff())) {
            if (con.getIsCanWriteOff() == 1) {
                userQw.lambda().eq(User::getIsWriteOffCardCoupon, EnableEnum.YES.getEnable());
            } else {
                userQw.lambda().and(wrapper -> wrapper.eq(User::getIsWriteOffCardCoupon, con.getIsCanWriteOff())
                        .or().isNull(User::getIsWriteOffCardCoupon));
            }
        }
        if (ObjectUtils.isNotEmpty(con.getEmpRemark())) {
            userQw.lambda().like(User::getEmpRemark, con.getEmpRemark());
        }
        if (ObjectUtils.isNotEmpty(con.getChannelEmpIds()) && !con.getChannelEmpIds().isEmpty()) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().in(UserCat::getChannelEmpIds, con.getChannelEmpIds());
            if (PageUserCatQw(userQw, userCatQw)) return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        if (ObjectUtils.isNotEmpty(con.getChannelSourceType())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().eq(UserCat::getChannelSource, con.getChannelSourceType());
            if (PageUserCatQw(userQw, userCatQw)) return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        if (ObjectUtils.isNotEmpty(con.getCatStartTime()) && ObjectUtils.isNotEmpty(con.getCatEndTime())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().between(UserCat::getCreateTime, con.getCatStartTime(), con.getCatEndTime());
            if (PageUserCatQw(userQw, userCatQw)) return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        if (ObjectUtils.isNotEmpty(con.getStartTakeDate()) && ObjectUtils.isNotEmpty(con.getEndTakeDate())) {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().ge(UserCat::getTakeDate, con.getStartTakeDate() + " 00:00:00")
                    .le(UserCat::getTakeDate, con.getEndTakeDate() + " 23:59:59");
            if (PageUserCatQw(userQw, userCatQw)) return new PageDTO<>(1L, 0L, new ArrayList<>());
        }
        userQw.lambda().orderByDesc(User::getId);
        Page<User> page = new Page<>(con.getCurrent(), con.getSize());
        Page<User> userPage = iUserService.page(page, userQw);
        if (userPage.getRecords().isEmpty()) {
            return new PageDTO<>(userPage.getCurrent(), userPage.getTotal(), new ArrayList<>());
        }
        List<Long> userIds = userPage.getRecords().stream().map(User::getId).collect(Collectors.toList());
        //查询用户订单数量
        CompletableFuture<Map<Long, LongSummaryStatistics>> orderMapFuture = YsThread.execute(() -> {
            QueryWrapper<Order> orderQw = new QueryWrapper<>();
            orderQw.lambda().in(Order::getUserId, userIds);
            return iOrderService.list(orderQw).stream().collect(
                    Collectors.groupingBy(Order::getUserId,
                            Collectors.summarizingLong(Order::getId)));
        });
        //查询用户猫咪余额
        CompletableFuture<Map<Long, LongSummaryStatistics>> userCatMapFuture = YsThread.execute(() -> {
            QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
            userCatQw.lambda().in(UserCat::getUserId, userIds);
            return iUserCatService.list(userCatQw).stream()
                    .collect(Collectors.groupingBy(UserCat::getUserId,
                            Collectors.summarizingLong(UserCat::getCatMoney)));
        });
        //查询会员等级
        CompletableFuture<Map<Long, MemberLevel>> memberLevelMapFuture = YsThread.execute(() -> {
            return iMemberLevelService.list().stream().collect(Collectors.toMap(MemberLevel::getId, it -> it));
        });
        //查询用户幺豆
        CompletableFuture<Map<Long, UserPulse>> userPulseMapFuture = YsThread.execute(() -> {
            return iUserPulseService.mapByUserIds(userIds);
        });
        Map<Long, MemberLevel> memberLevelMap = memberLevelMapFuture.join();
        Map<Long, LongSummaryStatistics> userCatMap = userCatMapFuture.join();
        Map<Long, LongSummaryStatistics> orderMap = orderMapFuture.join();
        Map<Long, UserPulse> userPulseMap = userPulseMapFuture.join();
        //整理数据
        List<UserVO> collect = userPage.getRecords().stream().map(it -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(it, userVO);
            userVO.setWriteOffHospitalIdList(JSONArray.parseArray(it.getWriteOffHospitalId(), Long.class));
            userVO.setWriteOffShopCode(JSONArray.parseArray(it.getWriteOffShopCode(), String.class));
            userVO.setPhone(YsStringUtil.disposePhone(it.getPhone()));
            if (userCatMap.containsKey(it.getId())) {
                userVO.setCatMoney(MoneyUtil.long2Str(userCatMap.get(it.getId()).getSum()));
                userVO.setCatCount(userCatMap.get(it.getId()).getCount());
            } else {
                userVO.setCatMoney("0.0");
                userVO.setCatCount(0L);
            }
            if (ObjectUtil.isNotEmpty(it.getChannelEmpIds())) {
                String[] split = it.getChannelEmpIds().split(",");
                List<Long> idList = Arrays.stream(split)
                        .map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
                userVO.setChannelEmpIds(idList);
            }
            if (orderMap.containsKey(it.getId())) {
                userVO.setOrderNum(orderMap.get(it.getId()).getCount());
            } else {
                userVO.setOrderNum(0L);
            }
            MemberLevelVO memberLevelVO = new MemberLevelVO();
            if (memberLevelMap.containsKey(it.getVipLevelId())) {
                BeanUtils.copyProperties(memberLevelMap.get(it.getVipLevelId()), memberLevelVO);
            }
            if (ObjectUtil.isNotEmpty(it.getUserTags())) {
                userVO.setTags(JSONArray.parseArray(it.getUserTags(), String.class));
            } else {
                userVO.setTags(new ArrayList<>());
            }
            UserPulse userPulse = userPulseMap.get(it.getId());
            if (ObjectUtils.isNotEmpty(userPulse)) {
                userVO.setUserPulse(MoneyUtil.long2Str(userPulse.getPulseNum()));
            } else {
                userVO.setUserPulse("0.0");
            }
            userVO.setMemberLevel(memberLevelVO);
            return userVO;
        }).collect(Collectors.toList());
        return new PageDTO<>(userPage.getCurrent(), userPage.getTotal(), collect);
    }

    private boolean PageUserCatQw(QueryWrapper<User> userQw, QueryWrapper<UserCat> userCatQw) {
        List<Long> collect = iUserCatService.list(userCatQw).stream().map(UserCat::getUserId).collect(Collectors.toList());
        if (collect.isEmpty()) {
            return true;
        }
        userQw.lambda().in(User::getId, collect);
        return false;
    }

}
